package org.abacus.hibernate;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * @author chaoyang.li
 * @since 2012-08-30
 */
public class HibernateSessionFactoryProvider {

	private Set<String> tags;

	private static HibernateSessionFactoryProvider instance;

	private Map<String, SessionFactory> sessionFactories;

	private Map<String, Configuration> configurations;

	private HibernateSessionFactoryProvider() {
		super();
		init();
	}

	/**
	 * @author chaoyang.li
	 */
	private void init() {
		tags = new HashSet<String>();
		sessionFactories = new ConcurrentHashMap<String, SessionFactory>();
		configurations = new ConcurrentHashMap<String, Configuration>();
	}

	/**
	 * @author chaoyang.li
	 */
	protected Set<String> getTags() {
		return tags;
	}

	/**
	 * @author chaoyang.li
	 */
	public synchronized static HibernateSessionFactoryProvider getInstance() {
		if (null == instance)
			instance = new HibernateSessionFactoryProvider();
		return instance;
	}

	/**
	 * @author chaoyang.li
	 * @param tag
	 */
	protected synchronized Configuration buildConfiguration(String tag) {
		Configuration configuration = configurations.get(tag);
		if (null == configuration) {
			configuration = new Configuration().configure(tag);
			configurations.put(tag, configuration);
		}
		return configuration;
	}

	/**
	 * @author chaoyang.li
	 * @param tag
	 */
	protected synchronized SessionFactory buildSessionFactory(String tag) {
		SessionFactory sessionFactory = sessionFactories.get(tag);
		if (null == sessionFactory) {
			sessionFactory = buildConfiguration(tag).buildSessionFactory();
			sessionFactories.put(tag, sessionFactory);
		}
		return sessionFactory;
	}

	/**
	 * @author chaoyang.li
	 * @param tag
	 */
	public void addTag(String tag) {
		tags.add(tag);
		buildSessionFactory(tag);
	}

	/**
	 * @author chaoyang.li
	 */
	protected synchronized void buildSessionFactories() {
		for (String tag : tags) {
			try {
				buildSessionFactory(tag);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}
